import * as winston from 'winston'
import i18n from '@/i18n'
import { createWinstonLogger } from './create-winston-logger'

export class AppLogger {
  /**
   * 日志根目录
   */
  static LOGS_STORE_ROOT = '../logs'

  /**
   * 日志实例
   */
  protected static winstonLogger: winston.Logger

  /**
   * logger getter
   */
  protected static get logger() {
    return this.winstonLogger || this.create({ storeRoot: this.LOGS_STORE_ROOT })
  }

  /**
   * 创建日志单例
   * @param option
   * @returns
   */
  static create(option: { storeRoot: string }) {
    if (this.winstonLogger) {
      return this.winstonLogger
    }

    this.winstonLogger = createWinstonLogger(option)

    return this.winstonLogger
  }

  /**
   * 设置日志级别
   * @param level
   */
  static setLevel(level: string) {
    this.logger.level = level
    return this
  }

  /**
   * 输出error级别日志
   * @param context 上下文
   * @param message 消息
   * @param messages 消息数组
   */
  static error(context: string, message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    if (this.logger.isErrorEnabled()) {
      this.logger.defaultMeta = { context }
      this.logger.error(resolveMessages(message, ...messages))
    }
  }

  /**
   * 输出warn级别日志
   * @param context 上下文
   * @param message 消息
   * @param messages 消息数组
   */
  static warn(context: string, message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    if (this.logger.isWarnEnabled()) {
      this.logger.defaultMeta = { context }
      this.logger.warn(resolveMessages(message, ...messages))
    }
  }

  /**
   * 输出info级别日志
   * @param context 上下文
   * @param message 消息
   * @param messages 消息数组
   */
  static info(context: string, message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    if (this.logger.isInfoEnabled()) {
      this.logger.defaultMeta = { context }
      this.logger.info(resolveMessages(message, ...messages))
    }
  }

  /**
   * 输出debug级别日志
   * @param context 上下文
   * @param message 消息
   * @param messages 消息数组
   */
  static debug(context: string, message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    if (this.logger.isDebugEnabled()) {
      this.logger.defaultMeta = { context }
      this.logger.debug(resolveMessages(message, ...messages))
    }
  }

  /**
   * 输出verbose级别日志
   * @param context 上下文
   * @param message 消息
   * @param messages 消息数组
   */
  static verbose(context: string, message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    if (this.logger.isVerboseEnabled()) {
      this.logger.defaultMeta = { context }
      this.logger.verbose(resolveMessages(message, ...messages))
    }
  }

  constructor(private context: string) {}

  /**
   * 设置上下文
   * @param context
   * @returns
   */
  setContext(context: string) {
    this.context = context
    return this
  }

  /**
   * 输出info级别日志
   * @param message 消息
   * @param messages 消息数组
   */
  info(message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    AppLogger.info(this.context, message, ...messages)
    return this
  }

  /**
   * 输出error级别日志
   * @param message 消息
   * @param messages 消息数组
   */
  error(message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    AppLogger.error(this.context, message, ...messages)
    return this
  }

  /**
   * 输出warn级别日志
   * @param message 消息
   * @param messages 消息数组
   */
  warn(message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    AppLogger.warn(this.context, message, ...messages)
    return this
  }

  /**
   * 输出debug级别日志
   * @param message 消息
   * @param messages 消息数组
   */
  debug(message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    AppLogger.debug(this.context, message, ...messages)
    return this
  }

  /**
   * 输出verbose级别日志
   * @param message 消息
   * @param messages 消息数组
   */
  verbose(message: AppLoggerMessage, ...messages: AppLoggerMessage[]) {
    AppLogger.verbose(this.context, message, ...messages)
    return this
  }

  /**
   * 记录callback耗时
   * @param label
   * @param callback
   * @returns
   */
  withProfile<R = void>(label: string, callback: () => R) {
    const lastProfileStartTimestamp = Date.now()
    try {
      return callback()
    } finally {
      this.debug(
        () =>
          `${label} ${i18n.t('lhy-common.logger.app-logger.12154291-0')} ${Date.now() - lastProfileStartTimestamp}ms`
      )
    }
  }

  /**
   * 记录callback耗时
   * @param label
   * @param callback
   * @returns
   */
  withPromiseProfile<R = void>(label: string, callback: () => Promise<R>) {
    const lastProfileStartTimestamp = Date.now()

    const end = () => {
      this.debug(
        () =>
          `${label} ${i18n.t('lhy-common.logger.app-logger.12154291-0')} ${Date.now() - lastProfileStartTimestamp}ms`
      )
    }

    return callback().then(
      res => {
        end()
        return res
      },
      err => {
        end()
        return Promise.reject(err)
      }
    )
  }
}

/**
 * 消息
 */
type AppLoggerMessage = any | (() => any)

/**
 * 解析消息
 * @param messages 消息数组
 * @returns 解析后的消息
 */
function resolveMessages(...messages: AppLoggerMessage[]) {
  return messages.map(message => (typeof message === 'function' ? message() : message)).join('\n')
}
